﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;

namespace SpaceNeedle.City6473.WebSite.App_Start
{
    public class ImageUtility
    {
        public static byte[] ImageToByteArray(System.Drawing.Image imageIn)
        {
            byte[] data = null;

            using (MemoryStream ms = new MemoryStream())
            {
                imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                data = ms.ToArray();
            }

            return data;
        }

        public static Image ByteArrayToImage(byte[] byteArrayIn)
        {
            Image returnImage = null;

            using (MemoryStream ms = new MemoryStream(byteArrayIn))
            {
                returnImage = Image.FromStream(ms);
            }

            return returnImage;
        }

        public static void SaveJpeg(Image img, string path, uint quality)
        {
            if (quality < 0)
            {
                quality = 0;
            }
            else if (quality > 100)
            {
                quality = 100;
            }

            // Encoder parameter for image quality 
            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        public static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats 
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec 
            for (int i = 0; i < codecs.Length; i++)
            {
                if (codecs[i].MimeType == mimeType)
                {
                    return codecs[i];
                }
            }

            return null;
        }

        public static Size Resize(Size originalSize, Size targetSize)
        {
            Size size = new Size();
            float ratio;

            if (targetSize.Width == 0)
            {
                ratio = (float)originalSize.Width / (float)originalSize.Height; //ratio by height
                size.Height = targetSize.Height;
                size.Width = Convert.ToInt32(targetSize.Height * ratio);

            }
            else
            {
                ratio = (float)originalSize.Height / (float)originalSize.Width; //ratio by width
                size.Height = Convert.ToInt32(targetSize.Width * ratio);
                size.Width = targetSize.Width;
            }

            return size;
        }

        public enum PicturePosition
        {
            Fill = 0,
            Fit = 1,
            Stretch = 2,
            Tile = 3,
            Center = 4
        }

        public static Rectangle Resize(Size originalSize, Size targetSize, PicturePosition picturePosition)
        {
            Rectangle rectangle = new Rectangle();

            float widthRatio = (float)originalSize.Width / (float)originalSize.Height;
            float heightRatio = (float)originalSize.Height / (float)originalSize.Width;

            switch (picturePosition)
            {
                #region Fill
                case PicturePosition.Fill:
                    if (widthRatio * targetSize.Height < targetSize.Width)//width smaller than screen bounds
                    {
                        rectangle.Width = targetSize.Width;
                        rectangle.Height = Convert.ToInt32(heightRatio * targetSize.Width);
                    }
                    else
                    {
                        rectangle.Height = targetSize.Height;
                        rectangle.Width = Convert.ToInt32(widthRatio * targetSize.Height);
                    }

                    rectangle.X = (targetSize.Width / 2) - (rectangle.Width / 2);
                    rectangle.Y = (targetSize.Height / 2) - (rectangle.Height / 2);

                    break;
                #endregion

                #region Center
                case PicturePosition.Center:
                    if (targetSize.Width > originalSize.Width && targetSize.Height > originalSize.Height)
                    {
                        rectangle.X = originalSize.Width / 2 - targetSize.Width / 2;
                        rectangle.Y = originalSize.Height / 2 - targetSize.Height / 2;
                        rectangle.Width = targetSize.Width;
                        rectangle.Height = targetSize.Height;
                    }
                    else
                    {
                        rectangle.X = 0;
                        rectangle.Y = 0;
                        rectangle.Width = targetSize.Width;
                        rectangle.Height = targetSize.Height;
                    }

                    break;
                #endregion

                #region Stretch
                case PicturePosition.Stretch:
                    rectangle.X = 0;
                    rectangle.Y = 0;
                    rectangle.Width = targetSize.Width;
                    rectangle.Height = targetSize.Height;
                    break;
                #endregion

                #region Fit
                case PicturePosition.Fit:
                    if (widthRatio * targetSize.Height > targetSize.Width) //width out of screen bounds
                    {
                        rectangle.Width = targetSize.Width;
                        rectangle.Height = Convert.ToInt32(heightRatio * targetSize.Width);
                    }
                    else
                    {
                        rectangle.Height = targetSize.Height;
                        rectangle.Width = Convert.ToInt32(widthRatio * targetSize.Height);
                    }

                    rectangle.X = (targetSize.Width / 2) - (rectangle.Width / 2);
                    rectangle.Y = (targetSize.Height / 2) - (rectangle.Height / 2);

                    break;
                #endregion
            }

            return rectangle;
        }

        public static Bitmap LoadImage(string path)
        {
            Bitmap bmp = null;

            try
            {
                using (Image image = Image.FromFile(path))
                {
                    bmp = ImageUtility.ResizeBitmap((Bitmap)image, image.Width, image.Height, PicturePosition.Stretch);
                }
            }
            catch { }

            return bmp;
        }

        public static Bitmap ResizeBitmapSuperFast(Bitmap image, int targetWidth, int targetHeight)
        {
            Bitmap newBitmap = new Bitmap(targetWidth, targetHeight, image.PixelFormat);

            using (Graphics graphics = Graphics.FromImage(newBitmap))
            {
                graphics.Clear(Color.Transparent);
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.SmoothingMode = SmoothingMode.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.Low;

                graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight));

                graphics.Flush();
            }

            return newBitmap;
        }

        public static Bitmap ResizeBitmapFast(Bitmap image, int targetWidth, int targetHeight, PicturePosition picturePosition)
        {
            Bitmap newBitmap = new Bitmap(targetWidth, targetHeight, image.PixelFormat);
            using (Graphics graphics = Graphics.FromImage(newBitmap))
            {
                graphics.Clear(Color.Transparent);
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.SmoothingMode = SmoothingMode.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.Low;

                switch (picturePosition)
                {
                    case PicturePosition.Fill:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Center:
                        if (image.Width < targetWidth && image.Height < targetHeight)
                        {
                            graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition), GraphicsUnit.Pixel);
                        }
                        else
                        {
                            graphics.DrawImage(image,
                                new Rectangle(0, 0, targetWidth, targetHeight),
                                new Rectangle((image.Width / 2) - (targetWidth / 2), (image.Height / 2) - (targetHeight / 2),
                               targetWidth, targetHeight), GraphicsUnit.Pixel);
                        }
                        break;
                    case PicturePosition.Stretch:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Tile:
                        for (int x = 0; x < (targetWidth / image.Width) + 1; x++)
                        {
                            for (int y = 0; y < (targetHeight / image.Height) + 1; y++)
                            {
                                graphics.DrawImage(image, new Rectangle(x * image.Width, y * image.Height, image.Width, image.Height));
                            }
                        }
                        break;
                    case PicturePosition.Fit:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                }

                graphics.Flush();
            }

            return newBitmap;
        }

        public static Bitmap ResizeBitmap(Bitmap image, int targetWidth, int targetHeight, PicturePosition picturePosition)
        {
            return ResizeBitmap(image, targetWidth, targetHeight, picturePosition, image.PixelFormat);

            //not necessary
            System.Drawing.Image newImage = new Bitmap(targetWidth, targetHeight, image.PixelFormat);
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                graphics.Clear(Color.Transparent);
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                switch (picturePosition)
                {
                    case PicturePosition.Fill:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Center:
                        //graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition), GraphicsUnit.Pixel);
                        if (image.Width < targetWidth && image.Height < targetHeight)
                        {
                            graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition), GraphicsUnit.Pixel);
                        }
                        else
                        {
                            graphics.DrawImage(image,
                                new Rectangle(0, 0, targetWidth, targetHeight),
                                new Rectangle((image.Width / 2) - (targetWidth / 2), (image.Height / 2) - (targetHeight / 2),
                               targetWidth, targetHeight), GraphicsUnit.Pixel);
                        }
                        break;
                    case PicturePosition.Stretch:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Tile:
                        for (int x = 0; x < (targetWidth / image.Width) + 1; x++)
                        {
                            for (int y = 0; y < (targetHeight / image.Height) + 1; y++)
                            {
                                graphics.DrawImage(image, new Rectangle(x * image.Width, y * image.Height, image.Width, image.Height));
                            }
                        }
                        break;
                    case PicturePosition.Fit:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                }

                graphics.Flush();
            }

            Bitmap result = (Bitmap)newImage.Clone();

            newImage.Dispose();

            return result;
        }

        public static Bitmap ResizeBitmap(Bitmap image, int targetWidth, int targetHeight, PicturePosition picturePosition, PixelFormat pixelFormat)
        {
            System.Drawing.Image newImage = new Bitmap(targetWidth, targetHeight);
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                graphics.Clear(Color.Transparent);
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

                switch (picturePosition)
                {
                    case PicturePosition.Fill:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Center:
                        //graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition), GraphicsUnit.Pixel);
                        if (image.Width < targetWidth && image.Height < targetHeight)
                        {
                            graphics.DrawImage(image, new Rectangle(0, 0, targetWidth, targetHeight), Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition), GraphicsUnit.Pixel);
                        }
                        else
                        {
                            graphics.DrawImage(image,
                                new Rectangle(0, 0, targetWidth, targetHeight),
                                new Rectangle((image.Width / 2) - (targetWidth / 2), (image.Height / 2) - (targetHeight / 2),
                               targetWidth, targetHeight), GraphicsUnit.Pixel);
                        }
                        break;
                    case PicturePosition.Stretch:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                    case PicturePosition.Tile:
                        for (int x = 0; x < (targetWidth / image.Width) + 1; x++)
                        {
                            for (int y = 0; y < (targetHeight / image.Height) + 1; y++)
                            {
                                graphics.DrawImage(image, new Rectangle(x * image.Width, y * image.Height, image.Width, image.Height));
                            }
                        }
                        break;
                    case PicturePosition.Fit:
                        graphics.DrawImage(image, Resize(new Size(image.Width, image.Height), new Size(targetWidth, targetHeight), picturePosition));
                        break;
                }

                graphics.Flush();
            }

            Bitmap result = (Bitmap)newImage.Clone();

            newImage.Dispose();

            return result;
        }

    }
}

